상품명 정규화와 가격 그룹핑 파이프라인
상품명 정규화와 가격 그룹핑 파이프라인
여러 언어와 표기 방식이 섞인 상품명을 구조화하고 가격 비교 그룹을 만드는 과정을 정리한다. 상품의 고유 식별과 시세 추정을 위한 그룹은 서로 다른 문제라는 점에서 출발한다.
본문의 코드는 특정 저장소 구현을 복사하지 않고 개념을 설명하기 위해 재구성한 예시다. 이름·경로·수치는 실제 운영 정보와 무관하다.
여러 시장에서 수집한 상품 제목은 사람이 읽어도 같은 상품인지 판단하기 어려운 경우가 많다.
LOUIS VUITTON Neverfull MM Monogram M40995
LV 네버풀 MM 모노그램 토트백
ルイヴィトン ネヴァーフルMM M41177
품번은 다르지만 시세를 계산할 때는 같은 증거 집합으로 봐도 되는 상품일 수 있다. 반대로 제목이 비슷해도 크기, 소재, 부속 장식에 따라 가격대가 크게 다를 수 있다.
이 문제를 풀면서 가장 중요했던 결론은 “상품의 identity와 가격 비교 그룹은 다르다”는 것이었다.
목차
- #상품 ID와 가격 그룹을 분리한다
- #제목을 구조화된 signal로 바꾸기
- #가격 그룹은 구체적인 키에서 시작한다
- #증거가 부족하면 점진적으로 fallback한다
- #평균보다 가중 중앙값
- #코드보다 리뷰 큐가 중요했다
- #결론
- #관련 노트
상품 ID와 가격 그룹을 분리한다
상품 카탈로그는 구체적일수록 좋다. 품번과 색상까지 포함한 하나의 제품을 식별할 수 있어야 한다.
하지만 가격 추정 그룹을 그렇게 세분화하면 증거가 부족해진다. 거래 1건으로 시세를 정하는 것은 안정적이지 않다.
따라서 다음 계층을 분리했다.
catalog model
└─ catalog product
└─ observations
price group
├─ catalog products
├─ observations
└─ current item estimates
catalog product는 상품 식별을 위한 객체이고, price group은 가격 증거를 공유할 수 있는 범위다.
제목을 구조화된 signal로 바꾸기
정규화 결과는 문자열 하나가 아니라 여러 signal의 집합이다.
brand: louis_vuitton
category: 가방
sub_category: 토트백_탑핸들
model_line: neverfull
size: mm
material: monogram
hardware: null
product_code: M40995
color: brown
이때 우선순위가 중요하다. 구체적인 신호가 일반적인 신호보다 먼저 적용되어야 한다.
확정된 product code
> 구체적인 model alias
> 제목에서 탐지한 model line
> 일반 패턴·소재 표현
예를 들어 matelasse처럼 소재와 패턴을 가리키는 단어를 항상 모델명으로 취급하면 서로 다른 제품이 하나의 모델로 합쳐진다. 품번이 확인된 경우에만 더 구체적인 모델로 승격시키는 방식이 필요했다.
가격 그룹은 구체적인 키에서 시작한다
기본 그룹 키는 다음 순서로 만들 수 있다.
brand|category|sub_category|model_line|size|material
가격에 큰 영향을 주는 제품군에서는 hardware까지 포함한다.
brand|category|sub_category|model_line|size|material|hardware
색상은 관측치에는 저장하지만 기본 그룹 키에서는 제외했다. 색까지 나누면 각 그룹의 증거 수가 급격히 줄어들기 때문이다. 충분한 거래가 있고 색상이 가격 분산을 실제로 설명하는 그룹에서만 나중에 추가하는 편이 낫다.
증거가 부족하면 점진적으로 fallback한다
가장 구체적인 그룹에 거래가 2건밖에 없다면 그 숫자를 시세로 보여주기 어렵다. 이때 유사도 점수로 아무 상품이나 섞는 대신 정의된 계층을 하나씩 넓힌다.
model + size + material + hardware
model + size + material
model + size
model
brand + category
매 단계에서 최소 증거 개수를 확인한다. 충분한 증거가 없다면 억지로 가격을 만들지 않고 no_evidence 또는 review 대상으로 보낸다.
평균보다 가중 중앙값
경매 가격에는 이상치가 많다. 단순 평균은 예외적으로 높은 낙찰가 하나에 큰 영향을 받는다. 유사도, 상품 상태, 거래 시점을 가중치로 두고 중앙값과 범위를 계산하면 더 안정적이다.
weight = similarity × condition_similarity × recency_weight
estimate = weighted median
range = weighted 20th ~ 80th percentile
날짜 가중치는 반감기 모델로 두었다.
recency_weight = 0.5 ^ (days_old / half_life_days)
결과를 정확한 단일 가격처럼 보여주기보다 예상 범위, 증거 수, 신뢰도를 함께 제시하는 것이 솔직하다.
코드보다 리뷰 큐가 중요했다
자동 정규화는 반드시 오류를 만든다. 모든 오류를 없애려고 하기보다 검토할 값이 큰 오류를 먼저 보여주는 구조가 필요했다.
unknown이 포함된 그룹- 증거 수가 적은 그룹
- 가격 분산이 큰 그룹
- 관측 건수가 많지만 모델을 알아내지 못한 제목
이 목록을 관측 건수 순으로 정렬하면 한 번의 규칙 개선으로 가장 많은 데이터를 개선할 수 있다.
모든 오류를 같은 비용으로 고치지 않는다. 관측 건수 × 오류 가능성 × 가격 영향도가 큰 항목부터 검토하면 규칙 개선의 효과가 빠르게 누적된다.
결론
시세 추정 파이프라인은 단순한 문자열 유사도 문제가 아니었다.
- 상품 identity와 가격 그룹을 분리한다.
- 구조화된 signal과 명시적 우선순위를 사용한다.
- 구체적인 그룹에서 넓은 그룹으로 점진적 fallback한다.
- 가중 중앙값과 범위, 신뢰도로 불확실성을 표현한다.
- 자동화 오류를 숨기지 않고 review queue로 보낸다.
데이터 파이프라인은 규칙을 한 번 완성하는 작업이 아니라 오류를 발견하고 우선순위를 정해 계속 개선하는 시스템에 가깝다.
관련 노트
- 정규화 — 데이터베이스 정규화의 목적과 단계
- SQL vs NoSQL — 데이터 모델과 저장소 선택 기준
- 유니코드와 UTF-8 — 다국어 문자열을 다룰 때 필요한 인코딩 기초